package practice.sort;

import org.jetbrains.annotations.NotNull;
import practice.sort.compare.*;

import java.text.DecimalFormat;

/**
 * @Description: 公共排序
 * @Author Ammar
 * @Create 2023/5/1 08:53
 */
public abstract class Sort implements Comparable<Sort> {
    protected Integer[] nums;
    private int cmpCount;
    private int swapCount;
    private long time;
    private DecimalFormat fmt = new DecimalFormat("#.00");

    public void sort(Integer[] array) {
        if(array == null || array.length < 2) return;
        this.nums = array;
        long begin = System.currentTimeMillis();
        sort();
        time = System.currentTimeMillis() - begin;
    }

    public abstract void sort();

    /**
     * 交换位置
     * @param i
     * @param j
     */
    protected void swap(int i, int j) {
        swapCount++;
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }

    @Override
    public int compareTo(@NotNull Sort o) {
        int result = (int)(time - o.time);
        if (result != 0) return result;

        result = cmpCount - o.cmpCount;
        if (result != 0) return result;

        return swapCount - o.swapCount;
    }

    @Override
    public String toString() {
        String timeStr = "耗时：" + (time / 1000.0) + "s(" + time + "ms)";
        String compareCountStr = "比较：" + numberString(cmpCount);
        String swapCountStr = "交换：" + numberString(swapCount);
        String stableStr = "稳定性：" + isStable();
        return "【" + getClass().getSimpleName() + "】\n"
                + stableStr + " \t"
                + timeStr + " \t"
                + compareCountStr + "\t "
                + swapCountStr + "\n"
                + "------------------------------------------------------------------";

    }

    private String numberString(int number) {
        if (number < 10000) return String.valueOf(number);

        if (number < 100000000) return fmt.format(number / 10000.0) + "万";
        return fmt.format(number / 100000000.0) + "亿";
    }

    private boolean isStable() {
        if (this instanceof BubbleSort) return true;
        if (this instanceof SelectionSort) return false;
        if (this instanceof HeapSort) return false;
        if (this instanceof InsertionSort) return true;
        if (this instanceof MergeSort) return true;
        if (this instanceof QuickSort) return false;
        if (this instanceof ShellSort) return false;
        if (this instanceof CountingSort) return true;
        if (this instanceof RadixSort) return true;
        return true;
    }

}
